1. Pandas - main classes and structure


In [240]:
%pylab
import pandas as pd
from pandas import Series, DataFrame


Using matplotlib backend: Qt4Agg
Populating the interactive namespace from numpy and matplotlib
WARNING: pylab import has clobbered these variables: ['f']
`%matplotlib` prevents importing * from pylab and numpy

Series 和 DataFrame

![Series 和 DataFrame](../jpgs/MyPicture1.jpg)

Series

Series 由一組 索引標籤+數據 組成,就如同Excel中的單一個 column


In [241]:
# Series 由一組 索引標籤+數據 組成
s = Series([4, 7, -5, 3])
s


Out[241]:
0    4
1    7
2   -5
3    3
dtype: int64

Series物件有 index 和 values屬性


In [242]:
# series的 index
# dtype是 int64
s.index


Out[242]:
RangeIndex(start=0, stop=4, step=1)

In [243]:
# series的 value
s.values


Out[243]:
array([ 4,  7, -5,  3], dtype=int64)

index如同Excel的 row number,但不一定是數字
和Excel最大的不同: Series 的 Index 可以有重複的值


In [244]:
s.index = pd.Index([0, 'a', 'a', 2])
s


Out[244]:
0    4
a    7
a   -5
2    3
dtype: int64

In [245]:
# 一個index可以對應多個rows
s['a']


Out[245]:
a    7
a   -5
dtype: int64

Series等同是一個 有序 字典

建構 Series物件的方式,索引不一定是數字


In [246]:
# 指定索引
s = Series([4, 7, -5, 3], index = ['d', 'b', 'a', 'c'])
s


Out[246]:
d    4
b    7
a   -5
c    3
dtype: int64

Series的index是一個 Index物件


In [247]:
# dtype是 object
s.index


Out[247]:
Index(['d', 'b', 'a', 'c'], dtype='object')

In [248]:
# 用索引取值
s['b']


Out[248]:
7

In [249]:
# 可以取多個值
s[['b', 'c']]


Out[249]:
b    7
c    3
dtype: int64

各種運算之後,還是會保留index


In [250]:
# 各種運算之後,還是會保留index
# 可以使用 陣列式索引
s[s > 3]


Out[250]:
d    4
b    7
dtype: int64

In [251]:
# 廣播運算
s * 2


Out[251]:
d     8
b    14
a   -10
c     6
dtype: int64

In [252]:
# 用 NumPy的頂級函示對Series做廣播運算
np.exp(s)


Out[252]:
d      54.598150
b    1096.633158
a       0.006738
c      20.085537
dtype: float64

In [253]:
# 可以將Series看成是一個有序字典
'b' in s
# 等同是 'b' in s.index


Out[253]:
True

In [254]:
'e' in s


Out[254]:
False

In [255]:
# 可以命名 Series物件
s.name = 'test'
s.name


Out[255]:
'test'

In [256]:
# 可以用Python字典來創建 Series
dt = {'Ohio' : 35000, 'Texas' : 71000, 'Oregon' : 16000, 'Utah' : 5000}
dt


Out[256]:
{'Ohio': 35000, 'Oregon': 16000, 'Texas': 71000, 'Utah': 5000}

Series等同是一個有序的字典


In [257]:
s1 = Series(dt)
s1
# Series等同是一個有序的字典


Out[257]:
Ohio      35000
Oregon    16000
Texas     71000
Utah       5000
dtype: int64

In [258]:
s1.index


Out[258]:
Index(['Ohio', 'Oregon', 'Texas', 'Utah'], dtype='object')

用 Index物件來設定 Series物件的 index屬性


In [259]:
# 建構Series的時候指定 index
# 其中 index California 在 dt中找不到,因此對應的value就標示為 NaN
states = ['Utah', 'California', 'Ohio', 'Oregon', 'Texas']
s2 = Series(dt, index = states)
s2


Out[259]:
Utah           5000.0
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
dtype: float64

pandas的頂級函式都可以對Series物件做廣播運算


In [260]:
# isnull, notnull 可用來檢測 NaN
pd.isnull(s2)


Out[260]:
Utah          False
California     True
Ohio          False
Oregon        False
Texas         False
dtype: bool

In [261]:
pd.notnull(s2)


Out[261]:
Utah           True
California    False
Ohio           True
Oregon         True
Texas          True
dtype: bool

Series物件也自帶很多ufunc


In [262]:
# Series 的 isnull(), notnull()
s2.isnull()


Out[262]:
Utah          False
California     True
Ohio          False
Oregon        False
Texas         False
dtype: bool

In [263]:
s2.notnull()


Out[263]:
Utah           True
California    False
Ohio           True
Oregon         True
Texas          True
dtype: bool

Series 最重要的功能之一 是能在算術運算中 自動對齊 不同索引的數據

依據index自動對齊


In [264]:
s1


Out[264]:
Ohio      35000
Oregon    16000
Texas     71000
Utah       5000
dtype: int64

In [265]:
s2


Out[265]:
Utah           5000.0
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
dtype: float64

In [266]:
s1 + s2


Out[266]:
California         NaN
Ohio           70000.0
Oregon         32000.0
Texas         142000.0
Utah           10000.0
dtype: float64

In [267]:
s1 * s2


Out[267]:
California             NaN
Ohio          1.225000e+09
Oregon        2.560000e+08
Texas         5.041000e+09
Utah          2.500000e+07
dtype: float64

可以直接修改index中索引的標籤,資料不會受到影響


In [268]:
# index可以隨時修改,會依照順序對應來修改
s2.index = ['Utah', 'New York', 'Ohio', 'Oregon', 'Texas']
s2


Out[268]:
Utah         5000.0
New York        NaN
Ohio        35000.0
Oregon      16000.0
Texas       71000.0
dtype: float64

DataFrame

DataFrame 是一個表格型的數據結構,有一組有序的列,每列可以是不同的資料類型。

DataFrame 既有列索引,也有行索引,

DataFrame可以被視為由一個或多個Series所組成的字典,等同是Excel的工作表

可以由等長的列表或字典 建構 DataFrame,字典頂層的每個item代表一個Series,也就是Excel工作表中的一個 column

由字典建立DataFrame的時候 columns 會自動以字母排序,除非顯式的以 columns參數指定


In [269]:
# 由等長的列表或字典 建構 DataFrame
data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'], 
        'year': [2000, 2001, 2002, 2001, 2002], 
        'pop': [1.5, 1.7, 3.6, 2.4, 2.9]}
frame = DataFrame(data)
frame


Out[269]:
pop state year
0 1.5 Ohio 2000
1 1.7 Ohio 2001
2 3.6 Ohio 2002
3 2.4 Nevada 2001
4 2.9 Nevada 2002

以字典建立DataFrame的時候,可以用columns參數指定 columns名稱與排序


In [270]:
# 可以指定columns的排序
data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'], 
        'year': [2000, 2001, 2002, 2001, 2002], 
        'pop': [1.5, 1.7, 3.6, 2.4, 2.9]}
frame = DataFrame(data, columns = ['state', 'year', 'pop'])
frame


Out[270]:
state year pop
0 Ohio 2000 1.5
1 Ohio 2001 1.7
2 Ohio 2002 3.6
3 Nevada 2001 2.4
4 Nevada 2002 2.9

In [271]:
# 找不到的column以NaN表示
data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'], 
        'year': [2000, 2001, 2002, 2001, 2002], 
        'pop': [1.5, 1.7, 3.6, 2.4, 2.9]}
frame = DataFrame(data,
                  columns = ['state', 'year', 'pop', 'debt'],
                  index = ['one', 'two', 'three', 'four', 'five']
                 )
frame


Out[271]:
state year pop debt
one Ohio 2000 1.5 NaN
two Ohio 2001 1.7 NaN
three Ohio 2002 3.6 NaN
four Nevada 2001 2.4 NaN
five Nevada 2002 2.9 NaN

In [272]:
# DataFrame的 columns 索引,也是一個 Index物件
frame.columns


Out[272]:
Index(['state', 'year', 'pop', 'debt'], dtype='object')

DataFrame的一個 column 就是一個 Series物件,可以用 column索引來取出,每個column也是DataFrame的一個屬性


In [273]:
# 將DataFrame的一個column取出成為一個Series
s = frame['state']
s


Out[273]:
one        Ohio
two        Ohio
three      Ohio
four     Nevada
five     Nevada
Name: state, dtype: object

In [274]:
# s 有 name屬性
s.name


Out[274]:
'state'

In [275]:
# 和 frame.state是一樣的,是一個Series
frame.state


Out[275]:
one        Ohio
two        Ohio
three      Ohio
four     Nevada
five     Nevada
Name: state, dtype: object

In [276]:
frame.year


Out[276]:
one      2000
two      2001
three    2002
four     2001
five     2002
Name: year, dtype: int64

由上可知,DataFrame可以被視為由一個或多個Series所組成的字典,字典的key是各個column索引的名稱

column索引 和 row索引,可以用'[]'或者'.'交互參照


In [277]:
# row 也可以透過索引取得,返回的是一個視圖,和原本的物件共用資料
frame.state.two


Out[277]:
'Ohio'

In [278]:
frame['state'].two


Out[278]:
'Ohio'

In [279]:
frame.state['two']


Out[279]:
'Ohio'

In [280]:
frame['state']['two']


Out[280]:
'Ohio'

對整個Series(column)賦值

是一種廣播


In [281]:
# 對整個Series賦值
frame.debt = 16.5
frame


Out[281]:
state year pop debt
one Ohio 2000 1.5 16.5
two Ohio 2001 1.7 16.5
three Ohio 2002 3.6 16.5
four Nevada 2001 2.4 16.5
five Nevada 2002 2.9 16.5

In [282]:
# 長度相同的情況下,會做 mapping
frame.debt = np.arange(5.)
frame


Out[282]:
state year pop debt
one Ohio 2000 1.5 0.0
two Ohio 2001 1.7 1.0
three Ohio 2002 3.6 2.0
four Nevada 2001 2.4 3.0
five Nevada 2002 2.9 4.0

如果將Series填入DataFrame,會依據index自動對齊


In [283]:
# 使用Series並指定index,並將之填入一個DataFrame, 則DataFrame中空缺的位置都會被填上NaN
s = Series([-1.2, -1.5, -1.7], index = ['two', 'four', 'five'])
frame.debt = s
frame


Out[283]:
state year pop debt
one Ohio 2000 1.5 NaN
two Ohio 2001 1.7 -1.2
three Ohio 2002 3.6 NaN
four Nevada 2001 2.4 -1.5
five Nevada 2002 2.9 -1.7

In [284]:
# 為不存在的column賦值會產生一個新的column
frame['eastern'] = (frame.state == 'Ohio')
frame


Out[284]:
state year pop debt eastern
one Ohio 2000 1.5 NaN True
two Ohio 2001 1.7 -1.2 True
three Ohio 2002 3.6 NaN True
four Nevada 2001 2.4 -1.5 False
five Nevada 2002 2.9 -1.7 False

In [285]:
frame['eastern']


Out[285]:
one       True
two       True
three     True
four     False
five     False
Name: eastern, dtype: bool

如果有指定column索引名稱,則該column的名稱就是其索引的名稱

如同Excel的欄位名稱


In [286]:
frame['eastern'].name


Out[286]:
'eastern'

可以以雙層的字典,一次性的建立DataFrame


In [287]:
# 以嵌套的字典建立DataFrame,外層的字典作為columns,內層的字典作為rows
pop = {'Nevada': {2001: 2.4, 2002: 2.9}, 
       'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}
pop


Out[287]:
{'Nevada': {2001: 2.4, 2002: 2.9}, 'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}

In [288]:
frame = DataFrame(pop)
frame


Out[288]:
Nevada Ohio
2000 NaN 1.5
2001 2.4 1.7
2002 2.9 3.6

In [289]:
# 也可以進行轉置
frame.T


Out[289]:
2000 2001 2002
Nevada NaN 2.4 2.9
Ohio 1.5 1.7 3.6

如果使用雙層字典來建立DataFrame,且指定的 row Index中沒有對準字典中的內層key,則以指定的row Index為準,沒對到的會被標示為NaN


In [290]:
# 內層的鍵會被合併、排序,但如果顯示地指定了索引,則不會合併或排序
DataFrame(pop, index = [2001, 2002, 2003])


Out[290]:
Nevada Ohio
2001 2.4 1.7
2002 2.9 3.6
2003 NaN NaN

In [291]:
# 可以設置 rows, columns 的名稱
frame.index.name = 'year'
frame.columns.name = 'state'
frame


Out[291]:
state Nevada Ohio
year
2000 NaN 1.5
2001 2.4 1.7
2002 2.9 3.6

In [292]:
# DataFrame 的 values屬性 返回一個二維 np.ndarray
v = frame.values
v


Out[292]:
array([[ nan,  1.5],
       [ 2.4,  1.7],
       [ 2.9,  3.6]])

索引(Index)物件

建構Series或者DataFrame的時候,所用到的任何數組或其他序列的標籤都會被轉換為一個 Index物件


In [293]:
obj = Series(range(3), name = 'd', index = ['a', 'b', 'c'])
obj


Out[293]:
a    0
b    1
c    2
Name: d, dtype: int32

In [294]:
index = obj.index
index # 是一個 Index物件


Out[294]:
Index(['a', 'b', 'c'], dtype='object')

In [295]:
index[1:]


Out[295]:
Index(['b', 'c'], dtype='object')

In [296]:
# Index物件是 immutable,不可以修改
# index[1] = 'b' # 會出錯

In [297]:
# 建立一個Index物件
index = pd.Index(np.arange(3))
index


Out[297]:
Int64Index([0, 1, 2], dtype='int64')

In [298]:
# 置換 Series物件的 index
obj.index = index
obj


Out[298]:
0    0
1    1
2    2
Name: d, dtype: int32

In [299]:
# 用Index物件來指定Series的index
obj2 = Series([1.5, -2.5, 0], index = index)
obj2


Out[299]:
0    1.5
1   -2.5
2    0.0
dtype: float64

In [300]:
obj2.index is index


Out[300]:
True

In [301]:
# Index 就像一個大小固定的 Set
frame


Out[301]:
state Nevada Ohio
year
2000 NaN 1.5
2001 2.4 1.7
2002 2.9 3.6

In [302]:
'Nevada' in frame.columns


Out[302]:
True

In [303]:
2002 in frame.index


Out[303]:
True

基本功能

重新索引


In [304]:
obj = Series([4.5, 7.2, -5.3, 3.6], index = ['d', 'b', 'a', 'c'])
obj


Out[304]:
d    4.5
b    7.2
a   -5.3
c    3.6
dtype: float64

reindex()用來移動row或者column的排列


In [305]:
# reindex方法會根據新索引重新排序資料
obj.reindex(['a', 'b', 'c', 'd', 'e'])


Out[305]:
a   -5.3
b    7.2
c    3.6
d    4.5
e    NaN
dtype: float64

In [306]:
# 可以指定 空缺資料的填充值 fill_value
obj.reindex(['a', 'b', 'c', 'd', 'e'], fill_value = 0)


Out[306]:
a   -5.3
b    7.2
c    3.6
d    4.5
e    0.0
dtype: float64

In [307]:
obj = Series(['blue', 'purple', 'yellow'], index = [0, 2, 4])
obj


Out[307]:
0      blue
2    purple
4    yellow
dtype: object

reindex()會依照指定的方式重新排列rows或者columns,可以指定若遇空缺時,插入rows或者columns的方式


In [308]:
# method參數可以以 "method" 指定 插值 的函式
obj.reindex(range(6), method = 'ffill')


Out[308]:
0      blue
1      blue
2    purple
3    purple
4    yellow
5    yellow
dtype: object

In [309]:
# 如果只傳入一個序列,則 .reindex()會優先對 row重新索引
frame = DataFrame(np.arange(9).reshape((3, 3)),
                  index = ['a', 'c', 'd'], 
                  columns = ['Ohio', 'Texas', 'California'])
frame


Out[309]:
Ohio Texas California
a 0 1 2
c 3 4 5
d 6 7 8

In [310]:
frame.reindex(['a', 'b', 'c', 'd'])


Out[310]:
Ohio Texas California
a 0.0 1.0 2.0
b NaN NaN NaN
c 3.0 4.0 5.0
d 6.0 7.0 8.0

使用reindex(),最好指定是針對row或者column


In [311]:
# 可以以 columns參數重新索引columns
frame.reindex(columns = ['Texas', 'Ohio', 'California'])


Out[311]:
Texas Ohio California
a 1 0 2
c 4 3 5
d 7 6 8

In [312]:
# 可以以 對 rows, columns都重新索引
frame.reindex(index = ['a', 'b', 'c', 'd'], 
              columns = ['Texas', 'Ohio', 'California'])


Out[312]:
Texas Ohio California
a 1.0 0.0 2.0
b NaN NaN NaN
c 4.0 3.0 5.0
d 7.0 6.0 8.0

In [313]:
# 插值
frame.reindex(index = ['a', 'b', 'c', 'd'], 
              columns = ['Texas', 'Ohio', 'California'], 
              method = 'ffill')


Out[313]:
Texas Ohio California
a 1 0 2
b 1 0 2
c 4 3 5
d 7 6 8

.ix[ ] 的索引方式很方便,只需傳入rows, columns 方向的索引列表


In [314]:
# 用 ix函式來重新索引
frame.ix[['a', 'b', 'c', 'd'],
         ['Texas', 'Ohio', 'California']]


Out[314]:
Texas Ohio California
a 1.0 0.0 2.0
b NaN NaN NaN
c 4.0 3.0 5.0
d 7.0 6.0 8.0

丟棄(drop)指定軸上的項


In [315]:
# 以一個索引數組指定要刪除的元素
obj = Series(np.arange(5.), index = ['a', 'b', 'c', 'd', 'e'])
obj


Out[315]:
a    0.0
b    1.0
c    2.0
d    3.0
e    4.0
dtype: float64

In [316]:
new_obj = obj.drop(['c'])
new_obj


Out[316]:
a    0.0
b    1.0
d    3.0
e    4.0
dtype: float64

In [317]:
new_obj = obj.drop(['c', 'd'])
new_obj


Out[317]:
a    0.0
b    1.0
e    4.0
dtype: float64

In [318]:
# 對於 DataFrame,可以刪除任意軸上的索引值
data = DataFrame(np.arange(16).reshape((4, 4)),
                 index = ['Ohio', 'Colorado', 'Utah', 'New York'], 
                 columns = ['one', 'two', 'three', 'four'])
data


Out[318]:
one two three four
Ohio 0 1 2 3
Colorado 4 5 6 7
Utah 8 9 10 11
New York 12 13 14 15

In [319]:
# 對於 DataFrame,可以刪除任意軸上的索引值
data.drop(['Colorado', 'Ohio'])


Out[319]:
one two three four
Utah 8 9 10 11
New York 12 13 14 15

In [320]:
# axis = 0 或省略,可以刪除rows
data.drop(['Colorado', 'Ohio'])


Out[320]:
one two three four
Utah 8 9 10 11
New York 12 13 14 15

In [321]:
# axis = 1,可以刪除columns
data.drop(['two', 'four'], axis = 1)


Out[321]:
one three
Ohio 0 2
Colorado 4 6
Utah 8 10
New York 12 14

索引、選取、過濾


In [322]:
# Series的索引值不只是整數
obj = Series(np.arange(4.), index = ['a', 'b', 'c', 'd'])
obj


Out[322]:
a    0.0
b    1.0
c    2.0
d    3.0
dtype: float64

In [323]:
# 單一值,不顯示索引
obj['b']


Out[323]:
1.0

In [324]:
# 單一值,不顯示索引
obj[1]


Out[324]:
1.0

In [325]:
# 多個值,顯示索引
obj[2:4]


Out[325]:
c    2.0
d    3.0
dtype: float64

In [326]:
# 多個值,顯示索引,依照指定的順序
obj[['b', 'a', 'd']]


Out[326]:
b    1.0
a    0.0
d    3.0
dtype: float64

In [327]:
# 多個值,顯示索引,依照指定的順序
obj[[1, 2, 3]]


Out[327]:
b    1.0
c    2.0
d    3.0
dtype: float64

In [328]:
# 多個值,顯示索引
obj[obj < 2]


Out[328]:
a    0.0
b    1.0
dtype: float64

In [329]:
# Series, DataFrame的切片算,其末端是包含的
obj['b':'d']


Out[329]:
b    1.0
c    2.0
d    3.0
dtype: float64

In [330]:
# 賦值的方式也很簡單
obj['b':'c'] = 5
obj


Out[330]:
a    0.0
b    5.0
c    5.0
d    3.0
dtype: float64

In [331]:
# 對於 DataFrame 索引,其實就是獲取一個或多個列
data = DataFrame(np.arange(16).reshape((4, 4)),
                 index = ['Ohio', 'Colorado', 'Utah', 'New York'], 
                 columns = ['one', 'two', 'three', 'four'])
data


Out[331]:
one two three four
Ohio 0 1 2 3
Colorado 4 5 6 7
Utah 8 9 10 11
New York 12 13 14 15

In [332]:
data[['two', 'four']]


Out[332]:
two four
Ohio 1 3
Colorado 5 7
Utah 9 11
New York 13 15

In [333]:
data[['four', 'two']]


Out[333]:
four two
Ohio 3 1
Colorado 7 5
Utah 11 9
New York 15 13

In [334]:
data[[1, 3]]


Out[334]:
two four
Ohio 1 3
Colorado 5 7
Utah 9 11
New York 13 15

In [335]:
# 這是row方向的切片
data[:2]


Out[335]:
one two three four
Ohio 0 1 2 3
Colorado 4 5 6 7

In [336]:
# 多層次的索引
data[data['three'] > 5]


Out[336]:
one two three four
Colorado 4 5 6 7
Utah 8 9 10 11
New York 12 13 14 15

In [337]:
# 透過 boolean型態的 DataFrame 進行索引
data


Out[337]:
one two three four
Ohio 0 1 2 3
Colorado 4 5 6 7
Utah 8 9 10 11
New York 12 13 14 15

In [338]:
# 透過 boolean型態的 DataFrame 進行索引
data < 5


Out[338]:
one two three four
Ohio True True True True
Colorado True False False False
Utah False False False False
New York False False False False

In [339]:
data[data < 5]


Out[339]:
one two three four
Ohio 0.0 1.0 2.0 3.0
Colorado 4.0 NaN NaN NaN
Utah NaN NaN NaN NaN
New York NaN NaN NaN NaN

ix 是重新索引的簡單方法


In [340]:
# ix 是重新索引的簡單方法
data.ix['Colorado', ['two', 'four']]


Out[340]:
two     5
four    7
Name: Colorado, dtype: int32

In [341]:
# ix 對兩軸重新索引,依照指定的順序
data.ix[['Colorado', 'Utah'], [3, 0, 1]]


Out[341]:
four one two
Colorado 7 4 5
Utah 11 8 9

In [342]:
# ix 索引,取出第0軸的第2個Series
data.ix[2]


Out[342]:
one       8
two       9
three    10
four     11
Name: Utah, dtype: int32

In [343]:
data.ix[: 'Utah', 'two']


Out[343]:
Ohio        1
Colorado    5
Utah        9
Name: two, dtype: int32

In [344]:
data.three > 5


Out[344]:
Ohio        False
Colorado     True
Utah         True
New York     True
Name: three, dtype: bool

In [345]:
# 對兩個軸索引,取出交集
data.ix[data.three > 5, :3]


Out[345]:
one two three
Colorado 4 5 6
Utah 8 9 10
New York 12 13 14

算數運算和數據對齊

pandas最重要的一個功能是: 可以對不同所引的對象進行算術運算。

在將對象相加時,若存在不同的索引,則結果的索引就是該索引對的聯集。


In [346]:
s1 = Series([7.3, -2.5, 3.4, 1.5], index = ['a', 'c', 'd', 'e'])
s2 = Series([-2.1, 3.6, -1.5, 4, 3.1], index = ['a', 'c', 'e', 'f', 'g'])

In [347]:
s1


Out[347]:
a    7.3
c   -2.5
d    3.4
e    1.5
dtype: float64

In [348]:
s2


Out[348]:
a   -2.1
c    3.6
e   -1.5
f    4.0
g    3.1
dtype: float64

In [349]:
# 兩個Series的索引會自動對齊,空缺的值填入NaN
s1 + s2


Out[349]:
a    5.2
c    1.1
d    NaN
e    0.0
f    NaN
g    NaN
dtype: float64

In [350]:
# 對於 DataFrame,索引自動對齊會發生在row 和 column方向
df1 = DataFrame(np.arange(9.).reshape((3, 3)),
                index = ['Ohio', 'Texas', 'Colorado'], 
                columns = list('bcd'))
df2 = DataFrame(np.arange(12.).reshape((4, 3)),
                index = ['Utah', 'Ohio', 'Texas', 'Oregon'], 
                columns = list('bde'))

In [351]:
df1


Out[351]:
b c d
Ohio 0.0 1.0 2.0
Texas 3.0 4.0 5.0
Colorado 6.0 7.0 8.0

In [352]:
df2


Out[352]:
b d e
Utah 0.0 1.0 2.0
Ohio 3.0 4.0 5.0
Texas 6.0 7.0 8.0
Oregon 9.0 10.0 11.0

In [353]:
df1 + df2


Out[353]:
b c d e
Colorado NaN NaN NaN NaN
Ohio 3.0 NaN 6.0 NaN
Oregon NaN NaN NaN NaN
Texas 9.0 NaN 12.0 NaN
Utah NaN NaN NaN NaN

在算術方法中填充值


In [354]:
df1 = DataFrame(np.arange(12.).reshape((3, 4)),
                columns = list('abcd'))
df2 = DataFrame(np.arange(20.).reshape((4, 5)),
                columns = list('abcde'))

In [355]:
df1


Out[355]:
a b c d
0 0.0 1.0 2.0 3.0
1 4.0 5.0 6.0 7.0
2 8.0 9.0 10.0 11.0

In [356]:
df2


Out[356]:
a b c d e
0 0.0 1.0 2.0 3.0 4.0
1 5.0 6.0 7.0 8.0 9.0
2 10.0 11.0 12.0 13.0 14.0
3 15.0 16.0 17.0 18.0 19.0

In [357]:
# 以指定的預設值取代 NaN作為自動填充值
# 但是兩個DataFrame都沒有的元素位置,還是會被填入NaN
df1.add(df2, fill_value = 0)


Out[357]:
a b c d e
0 0.0 2.0 4.0 6.0 4.0
1 9.0 11.0 13.0 15.0 9.0
2 18.0 20.0 22.0 24.0 14.0
3 15.0 16.0 17.0 18.0 19.0

In [358]:
# 重新索引的時候,也可以指定填充值
df1.reindex(columns = df2.columns, fill_value = 0)


Out[358]:
a b c d e
0 0.0 1.0 2.0 3.0 0
1 4.0 5.0 6.0 7.0 0
2 8.0 9.0 10.0 11.0 0

DataFrame 和 Series中間的運算


In [359]:
arr = np.arange(12.).reshape((3, 4))

In [360]:
arr


Out[360]:
array([[  0.,   1.,   2.,   3.],
       [  4.,   5.,   6.,   7.],
       [  8.,   9.,  10.,  11.]])

In [361]:
arr[0]


Out[361]:
array([ 0.,  1.,  2.,  3.])

In [362]:
# 算術運算 會進行 廣播
arr - arr[0]


Out[362]:
array([[ 0.,  0.,  0.,  0.],
       [ 4.,  4.,  4.,  4.],
       [ 8.,  8.,  8.,  8.]])

In [363]:
# DataFrame 和 Series 之間也是如此
df = DataFrame(np.arange(12.).reshape((4, 3)),
               columns = list("bde"), 
               index = ['Utah', 'Ohio', 'Texas', 'Oregon'])
df


Out[363]:
b d e
Utah 0.0 1.0 2.0
Ohio 3.0 4.0 5.0
Texas 6.0 7.0 8.0
Oregon 9.0 10.0 11.0

In [364]:
s = df.ix[0]
s


Out[364]:
b    0.0
d    1.0
e    2.0
Name: Utah, dtype: float64

In [365]:
# 也是進行廣播
# 會將Series的索引批被盜DataFrame的columns, 然後沿著rows(軸0)的方向一直向下廣播
df + s


Out[365]:
b d e
Utah 0.0 2.0 4.0
Ohio 3.0 5.0 7.0
Texas 6.0 8.0 10.0
Oregon 9.0 11.0 13.0

In [366]:
# 如果索引不同,則索引會聯集之後自動對齊
df


Out[366]:
b d e
Utah 0.0 1.0 2.0
Ohio 3.0 4.0 5.0
Texas 6.0 7.0 8.0
Oregon 9.0 10.0 11.0

In [367]:
s2 = df['d']
s2


Out[367]:
Utah       1.0
Ohio       4.0
Texas      7.0
Oregon    10.0
Name: d, dtype: float64

In [368]:
# 如果希望索引自動匹配且在row方向上廣播,則必須用算術運算方法
# 傳入的軸就是希望匹配的軸
df.add(s2, axis = 0)


Out[368]:
b d e
Utah 1.0 2.0 3.0
Ohio 7.0 8.0 9.0
Texas 13.0 14.0 15.0
Oregon 19.0 20.0 21.0

函數應用和映射

NumPy的 ufuncs (元素級數組方法) 也可用於操作pandas物件


In [369]:
frame = DataFrame(np.random.randn(4, 3),
                  columns = list('bde'),
                  index = ['Utah', 'Ohio', 'Texas', 'Oregon'])
frame


Out[369]:
b d e
Utah -0.499291 0.369832 0.124404
Ohio -0.421528 0.456171 0.823445
Texas -0.243567 -1.019749 -1.459779
Oregon -0.664238 0.102812 -0.694787

In [370]:
# NumPy的 ufuncs (元素級數組方法) 也可用於操作pandas物件
np.abs(frame)


Out[370]:
b d e
Utah 0.499291 0.369832 0.124404
Ohio 0.421528 0.456171 0.823445
Texas 0.243567 1.019749 1.459779
Oregon 0.664238 0.102812 0.694787

In [371]:
# DataFrame 上的 apply方法,可以實現元素級的運算
f = lambda x: x.max() - x.min()
frame.apply(f) # 預設會對每個 column操作


Out[371]:
b    0.420671
d    1.475919
e    2.283224
dtype: float64

In [372]:
# 沿著軸1
frame.apply(f, axis = 1)


Out[372]:
Utah      0.869123
Ohio      1.244973
Texas     1.216212
Oregon    0.797598
dtype: float64

In [373]:
frame


Out[373]:
b d e
Utah -0.499291 0.369832 0.124404
Ohio -0.421528 0.456171 0.823445
Texas -0.243567 -1.019749 -1.459779
Oregon -0.664238 0.102812 -0.694787

In [374]:
# 返回 由多個值組成的Series
def f(x):
    return Series([x.min(), x.max()], index = ['min', 'max'])
frame.apply(f) # 會對每個column操作 f,每個column傳回一個Series,再重新組合成DataFrame


Out[374]:
b d e
min -0.664238 -1.019749 -1.459779
max -0.243567 0.456171 0.823445

In [375]:
# DataFrame 也可以透過 applymap(), 使用Python元素級的函式
f = lambda x: "{0:.3f}".format(x)
frame.applymap(f)


Out[375]:
b d e
Utah -0.499 0.370 0.124
Ohio -0.422 0.456 0.823
Texas -0.244 -1.020 -1.460
Oregon -0.664 0.103 -0.695

In [376]:
# Series 也可以透過 map(), 使用Python元素級的函式
f = lambda x: "{0:.3f}".format(x)
f2 = frame['b']
f2.map(f)


Out[376]:
Utah      -0.499
Ohio      -0.422
Texas     -0.244
Oregon    -0.664
Name: b, dtype: object

排序和排名

排序


In [377]:
# 可以使用 sort_index方法 來對軸索引排序
obj = Series(range(4), index = list('dabc'))
obj


Out[377]:
d    0
a    1
b    2
c    3
dtype: int32

In [378]:
# 可以使用 sort_index方法 來對軸索引排序
# 是針對索引來排序,而不是針對資料值
obj.sort_index()


Out[378]:
a    1
b    2
c    3
d    0
dtype: int32

In [379]:
# DataFrame 也可以使用 sort_index 並指定軸來排序索引
frame = DataFrame(np.arange(8).reshape((2, 4)),
                  index = ['three', 'one'],
                  columns = list('dabc')
                 )
frame


Out[379]:
d a b c
three 0 1 2 3
one 4 5 6 7

In [380]:
frame.sort_index(axis = 0)


Out[380]:
d a b c
one 4 5 6 7
three 0 1 2 3

In [381]:
frame.sort_index(axis = 1)


Out[381]:
a b c d
three 1 2 3 0
one 5 6 7 4

In [382]:
# 可以串接
frame.sort_index(axis = 0).sort_index(axis = 1)


Out[382]:
a b c d
one 5 6 7 4
three 1 2 3 0

In [383]:
# 可以指定 降幕 排序
frame.sort_index(axis = 1, ascending = False)


Out[383]:
d c b a
three 0 3 2 1
one 4 7 6 5

In [384]:
# 若要以值來排序,可以使用 sort_values()方法
obj['b'] = 4
print(obj)
obj.sort_values()


d    0
a    1
b    4
c    3
dtype: int32
Out[384]:
d    0
a    1
c    3
b    4
dtype: int32

In [385]:
# 若以sort_values()方法排序,空缺的值會被排到最後面
obj['a'] = None
print(obj)
obj.sort_values()


d    0.0
a    NaN
b    4.0
c    3.0
dtype: float64
Out[385]:
d    0.0
c    3.0
b    4.0
a    NaN
dtype: float64

In [386]:
# 要根據一個或多個column中的值來排序,可以使用 sort_values()
frame = DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]})
frame


Out[386]:
a b
0 0 4
1 1 7
2 0 -3
3 1 2

In [387]:
# 使用 sort_values() 根據值來排序
frame.sort_values('b')


Out[387]:
a b
2 0 -3
3 1 2
0 0 4
1 1 7

In [388]:
# 使用 sort_values() 根據多個columns的值來排序
frame.sort_values(['a', 'b'])


Out[388]:
a b
2 0 -3
0 0 4
3 1 2
1 1 7

彙總和計算描述統計


In [389]:
df = DataFrame([[1.4, np.nan], [7.1, -4.5], 
               [np.nan, np.nan], [0.75, -1.3]], 
               index = list('abcd'), 
               columns = ['one', 'two'])
df


Out[389]:
one two
a 1.40 NaN
b 7.10 -4.5
c NaN NaN
d 0.75 -1.3

In [390]:
# sum()傳回一個Series
df.sum()


Out[390]:
one    9.25
two   -5.80
dtype: float64

In [391]:
# 指定軸向做 sum()
df.sum(axis = 1)


Out[391]:
a    1.40
b    2.60
c    0.00
d   -0.55
dtype: float64

In [392]:
# NaN會被自動排除(當作0),可以使用skipna參數改變
df.sum(axis = 1, skipna = False)


Out[392]:
a     NaN
b    2.60
c     NaN
d   -0.55
dtype: float64

In [393]:
# idxmin, idxmax 傳回間接統計,最大值或最小值的索引
df.idxmin()


Out[393]:
one    d
two    b
dtype: object

In [394]:
df.idxmax()


Out[394]:
one    b
two    d
dtype: object

In [395]:
# 累積加總 cumsum()
df.cumsum()


Out[395]:
one two
a 1.40 NaN
b 8.50 -4.5
c NaN NaN
d 9.25 -5.8

In [396]:
# describe 可以一次性產生多種統計數字
df.describe()


Out[396]:
one two
count 3.000000 2.000000
mean 3.083333 -2.900000
std 3.493685 2.262742
min 0.750000 -4.500000
25% 1.075000 -3.700000
50% 1.400000 -2.900000
75% 4.250000 -2.100000
max 7.100000 -1.300000

In [397]:
# describe 對非數字資料,產生另外一種統計數字
obj = Series(list('aabc') * 4)
obj


Out[397]:
0     a
1     a
2     b
3     c
4     a
5     a
6     b
7     c
8     a
9     a
10    b
11    c
12    a
13    a
14    b
15    c
dtype: object

In [398]:
obj.describe()


Out[398]:
count     16
unique     3
top        a
freq       8
dtype: object

相關係數與協方差


In [399]:
# 透過 參數對 計算出來的 彙總統計(如 相關係數和協方差)
import pandas.io.data as web
# from pandas_datareader import data, wb

all_data = {}

for ticker in ['AAPL', 'IBM', 'MSFT', 'GOOG']:
    all_data[ticker] = web.get_data_yahoo(ticker, '1/1/2013', '1/1/2015')
    
price = DataFrame({tic: data['Adj Close'] for tic, data in all_data.items()})
volume = DataFrame({tic: data['Volume'] for tic, data in all_data.items()})

In [400]:
# 百分比變化
returns = price.pct_change()
returns.tail()


Out[400]:
AAPL GOOG IBM MSFT
Date
2014-12-24 -0.004709 -0.003430 -0.002589 -0.006398
2014-12-26 0.017677 0.009948 0.003213 -0.005401
2014-12-29 -0.000702 -0.006928 -0.011273 -0.008981
2014-12-30 -0.012203 0.000170 -0.002866 -0.009062
2014-12-31 -0.019019 -0.007579 0.002437 -0.012122

In [401]:
# corr() 用來計算相關係數
returns.MSFT.corr(returns.IBM)


Out[401]:
0.26199996452035351

In [402]:
# cov()用來計算協方差
returns.MSFT.cov(returns.IBM)


Out[402]:
4.0951215814169915e-05

In [403]:
# DataFrame的 corr(), cov() 將會返回相同形狀的矩陣
returns.corr()


Out[403]:
AAPL GOOG IBM MSFT
AAPL 1.000000 0.168597 0.140436 0.135613
GOOG 0.168597 1.000000 0.275024 0.327994
IBM 0.140436 0.275024 1.000000 0.262000
MSFT 0.135613 0.327994 0.262000 1.000000

In [404]:
returns.cov()


Out[404]:
AAPL GOOG IBM MSFT
AAPL 0.000253 0.000036 0.000025 0.000030
GOOG 0.000036 0.000185 0.000042 0.000062
IBM 0.000025 0.000042 0.000127 0.000041
MSFT 0.000030 0.000062 0.000041 0.000193

In [405]:
# 利用DataFrame的 corrwith()方法,可以計算列或行 跟另外一個Series或DataFrame之間的相關係數
returns.corrwith(returns.IBM)


Out[405]:
AAPL    0.140436
GOOG    0.275024
IBM     1.000000
MSFT    0.262000
dtype: float64

In [406]:
returns.corrwith(volume)


Out[406]:
AAPL   -0.134204
GOOG    0.231548
IBM    -0.343626
MSFT   -0.025271
dtype: float64

唯一值、值計數與成員資格


In [407]:
obj = Series(list('cadaabbcc'))
obj


Out[407]:
0    c
1    a
2    d
3    a
4    a
5    b
6    b
7    c
8    c
dtype: object

In [408]:
# uniquie 唯一值
obj.unique()


Out[408]:
array(['c', 'a', 'd', 'b'], dtype=object)

In [409]:
# 排序之後的唯一值
np.sort(obj.unique())


Out[409]:
array(['a', 'b', 'c', 'd'], dtype=object)

In [410]:
# value_count()傳回 各值出現的次數,依照出現的次數降幕排序
obj.value_counts()


Out[410]:
a    3
c    3
b    2
d    1
dtype: int64

In [411]:
# value_counts()可以做為頂層函式,依照出現的次數降幕排序
pd.value_counts(obj)


Out[411]:
a    3
c    3
b    2
d    1
dtype: int64

In [412]:
# 可以使用 sort 參數 禁止排序
pd.value_counts(obj, sort = False)


Out[412]:
b    2
c    3
a    3
d    1
dtype: int64

In [413]:
# 用 isin() 判斷成員資格
mask = obj.isin(['b', 'c'])

In [414]:
mask


Out[414]:
0     True
1    False
2    False
3    False
4    False
5     True
6     True
7     True
8     True
dtype: bool

處理缺失數據(missing data)


In [415]:
# 以NaN標示缺失數據
s = Series(['aardradf', 'asdfasfas', np.nan, 'asdfasfasf'])
s


Out[415]:
0      aardradf
1     asdfasfas
2           NaN
3    asdfasfasf
dtype: object

In [416]:
# 用 isnull()來檢驗NaN
s.isnull()


Out[416]:
0    False
1    False
2     True
3    False
dtype: bool

In [417]:
# None等同於 NaN
s[0] = None
s.isnull()


Out[417]:
0     True
1    False
2     True
3    False
dtype: bool

濾除缺失數據


In [418]:
from numpy import nan as NA
data = Series([1, NA, 3.5, NA, 7])
data


Out[418]:
0    1.0
1    NaN
2    3.5
3    NaN
4    7.0
dtype: float64

In [419]:
# 用 dropna()捨棄 NA,index 並不會重新設定
data.dropna()


Out[419]:
0    1.0
2    3.5
4    7.0
dtype: float64

In [420]:
# 也可透過 boolean型索引過濾
data[data.notnull()]


Out[420]:
0    1.0
2    3.5
4    7.0
dtype: float64

In [421]:
# 對 DataFrame來說,dropna()預設捨棄任何有NA的row
df = DataFrame([[1., 6.5, 3.], [1., NA, NA], [NA, NA, NA],[NA, 6.5, 3.]])
df


Out[421]:
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
2 NaN NaN NaN
3 NaN 6.5 3.0

In [422]:
# dropna()預設捨棄任何有NA的row
df.dropna()


Out[422]:
0 1 2
0 1.0 6.5 3.0

In [423]:
# 若傳入 how='all',則只捨棄 所有數值皆為NA的那個row
df.dropna(how='all')


Out[423]:
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
3 NaN 6.5 3.0

In [424]:
# 要用這種方式捨棄column,則需傳入 axis=1即可
df[3] = NA
df


Out[424]:
0 1 2 3
0 1.0 6.5 3.0 NaN
1 1.0 NaN NaN NaN
2 NaN NaN NaN NaN
3 NaN 6.5 3.0 NaN

In [425]:
# 傳入 axis=1,捨棄整列為NA的column
df.dropna(axis = 1, how = 'all')


Out[425]:
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
2 NaN NaN NaN
3 NaN 6.5 3.0

In [426]:
# 使用 thresh 參數,只留下一部分觀測數據
df = DataFrame(np.random.randn(7, 3))
df


Out[426]:
0 1 2
0 0.642367 -1.339694 1.649716
1 -1.300356 -0.612324 1.177013
2 0.053202 0.050349 -0.544562
3 -0.792341 1.201260 -0.452149
4 1.019258 -1.642269 -0.409883
5 -0.455651 -0.634352 0.435666
6 0.947129 1.184143 0.936049

In [427]:
df.ix[:4, 1] = NA
df.ix[:2, 2] = NA
df


Out[427]:
0 1 2
0 0.642367 NaN NaN
1 -1.300356 NaN NaN
2 0.053202 NaN NaN
3 -0.792341 NaN -0.452149
4 1.019258 NaN -0.409883
5 -0.455651 -0.634352 0.435666
6 0.947129 1.184143 0.936049

In [428]:
# 用 thresh 參數
df.dropna(thresh = 3)


Out[428]:
0 1 2
5 -0.455651 -0.634352 0.435666
6 0.947129 1.184143 0.936049

填充缺失數據


In [429]:
# 使用 fillna()來填充缺失數據
df.fillna(0)


Out[429]:
0 1 2
0 0.642367 0.000000 0.000000
1 -1.300356 0.000000 0.000000
2 0.053202 0.000000 0.000000
3 -0.792341 0.000000 -0.452149
4 1.019258 0.000000 -0.409883
5 -0.455651 -0.634352 0.435666
6 0.947129 1.184143 0.936049

In [430]:
# 依據字典,對不同的column填充不同的值
df.fillna({1: 0.5, 2: -1})


Out[430]:
0 1 2
0 0.642367 0.500000 -1.000000
1 -1.300356 0.500000 -1.000000
2 0.053202 0.500000 -1.000000
3 -0.792341 0.500000 -0.452149
4 1.019258 0.500000 -0.409883
5 -0.455651 -0.634352 0.435666
6 0.947129 1.184143 0.936049

In [431]:
# fillna()預設傳回副本,但也可以用 inplace 參數來就地修改
df.fillna(0, inplace = True)
df


Out[431]:
0 1 2
0 0.642367 0.000000 0.000000
1 -1.300356 0.000000 0.000000
2 0.053202 0.000000 0.000000
3 -0.792341 0.000000 -0.452149
4 1.019258 0.000000 -0.409883
5 -0.455651 -0.634352 0.435666
6 0.947129 1.184143 0.936049

In [432]:
# 差值的方法 ffill, bfill
df = DataFrame(np.random.randn(6, 3))
df.ix[2:, 1] = NA
df.ix[4:, 2] = NA
df


Out[432]:
0 1 2
0 0.357480 -0.061618 0.367091
1 0.783698 0.781409 0.265097
2 -1.276144 NaN -1.951159
3 -0.257126 NaN 0.778956
4 -0.713192 NaN NaN
5 -0.403955 NaN NaN

In [433]:
# 'ffill'的插值方式
df.fillna(method = 'ffill')


Out[433]:
0 1 2
0 0.357480 -0.061618 0.367091
1 0.783698 0.781409 0.265097
2 -1.276144 0.781409 -1.951159
3 -0.257126 0.781409 0.778956
4 -0.713192 0.781409 0.778956
5 -0.403955 0.781409 0.778956

In [434]:
# 限制插值的次數
df.fillna(method = 'ffill', limit = 2)


Out[434]:
0 1 2
0 0.357480 -0.061618 0.367091
1 0.783698 0.781409 0.265097
2 -1.276144 0.781409 -1.951159
3 -0.257126 0.781409 0.778956
4 -0.713192 NaN 0.778956
5 -0.403955 NaN 0.778956

In [435]:
# 用 mean 作為插入值
df.fillna(df.mean())


Out[435]:
0 1 2
0 0.357480 -0.061618 0.367091
1 0.783698 0.781409 0.265097
2 -1.276144 0.359895 -1.951159
3 -0.257126 0.359895 0.778956
4 -0.713192 0.359895 -0.135004
5 -0.403955 0.359895 -0.135004

層次化索引(hierachical indexing)


In [436]:
# 使用 MultiIndex 索引的Series的格式化輸出形式
# 可以用一維的方式來表達二維的資料,以低維度的形式來處理高維度的資料
s = Series(np.random.randn(10),
           index = [list('aaabbbccdd'),  [1, 2, 3, 1, 2, 3, 1, 2, 2, 3]])
s


Out[436]:
a  1    0.071582
   2   -1.306458
   3    0.667916
b  1    0.131727
   2   -0.009593
   3    0.026805
c  1    1.964970
   2    0.912628
d  2    0.493484
   3    0.907770
dtype: float64

In [437]:
s.index


Out[437]:
MultiIndex(levels=[['a', 'b', 'c', 'd'], [1, 2, 3]],
           labels=[[0, 0, 0, 1, 1, 1, 2, 2, 3, 3], [0, 1, 2, 0, 1, 2, 0, 1, 1, 2]])

In [438]:
# 選取數據 子集合
s['b']


Out[438]:
1    0.131727
2   -0.009593
3    0.026805
dtype: float64

In [439]:
s['b':'c']


Out[439]:
b  1    0.131727
   2   -0.009593
   3    0.026805
c  1    1.964970
   2    0.912628
dtype: float64

In [440]:
s.ix[['b', 'c']]


Out[440]:
b  1    0.131727
   2   -0.009593
   3    0.026805
c  1    1.964970
   2    0.912628
dtype: float64

In [441]:
# 選取 內層 的數據
s[:, 2]


Out[441]:
a   -1.306458
b   -0.009593
c    0.912628
d    0.493484
dtype: float64

In [442]:
# 數據可以透過 unstack 方法被重新安排到一個 DataFrame中
s.unstack()


Out[442]:
1 2 3
a 0.071582 -1.306458 0.667916
b 0.131727 -0.009593 0.026805
c 1.964970 0.912628 NaN
d NaN 0.493484 0.907770

In [443]:
# unstack 的逆運算是 stack
s.unstack().stack()


Out[443]:
a  1    0.071582
   2   -1.306458
   3    0.667916
b  1    0.131727
   2   -0.009593
   3    0.026805
c  1    1.964970
   2    0.912628
d  2    0.493484
   3    0.907770
dtype: float64

In [444]:
# 對於一個 DataFrame,每條軸都可以有分層索引
df = DataFrame(np.arange(12).reshape((4, 3)), 
               index = [['a', 'a', 'b', 'b'], [1, 2, 1, 2]], 
               columns = [['Ohio', 'Ohio', 'Colorado'], ['Green', 'Red', 'Green']])
df


Out[444]:
Ohio Colorado
Green Red Green
a 1 0 1 2
2 3 4 5
b 1 6 7 8
2 9 10 11

In [445]:
# 每層的索引都可以有名字
df.index.names = ['key1', 'key2']
df.columns.names = ['state', 'color']
df


Out[445]:
state Ohio Colorado
color Green Red Green
key1 key2
a 1 0 1 2
2 3 4 5
b 1 6 7 8
2 9 10 11

In [446]:
# 可以藉由索引來選取列分組
df['Colorado']


Out[446]:
color Green
key1 key2
a 1 2
2 5
b 1 8
2 11

In [447]:
# 可以先建構好 MultiIndex 物件,再用來創建 DataFrame物件
mi = pd.MultiIndex.from_arrays([['Ohio', 'Ohio', 'Colorado'], ['Green', 'Red', 'Green']], names = ['state', 'color'])
mi


Out[447]:
MultiIndex(levels=[['Colorado', 'Ohio'], ['Green', 'Red']],
           labels=[[1, 1, 0], [0, 1, 0]],
           names=['state', 'color'])

重排分級順序


In [448]:
# 用 swaplevel 互換級別
df.swaplevel('key1', 'key2')


Out[448]:
state Ohio Colorado
color Green Red Green
key2 key1
1 a 0 1 2
2 a 3 4 5
1 b 6 7 8
2 b 9 10 11

In [449]:
# sortlevel 根據單一個級別中的值對數據進行排序
df.swaplevel('key1', 'key2').sortlevel(0)


Out[449]:
state Ohio Colorado
color Green Red Green
key2 key1
1 a 0 1 2
b 6 7 8
2 a 3 4 5
b 9 10 11

In [450]:
df.swaplevel('key1', 'key2').sortlevel(1)


Out[450]:
state Ohio Colorado
color Green Red Green
key2 key1
1 a 0 1 2
2 a 3 4 5
1 b 6 7 8
2 b 9 10 11

根據級別彙總統計


In [451]:
# 設定 level 參數,用來指定對某個索引級別來操作統計函式
df.sum(level = 'key2')


Out[451]:
state Ohio Colorado
color Green Red Green
key2
1 6 8 10
2 12 14 16

In [452]:
# 對column上的索引級別來操作統計函式
df.sum(axis = 1, level = 'color')


Out[452]:
color Green Red
key1 key2
a 1 2 1
2 8 4
b 1 14 7
2 20 10

使用DataFrame的列


In [453]:
# 將 DataFrame的一個或多個列當作行索引來用,或者希望將行索引變成DataFrame的列
df = DataFrame({'a': range(7), 'b': range(7, 0, -1), 
                'c': ['one', 'one', 'one', 'two', 'two', 'two', 'two'], 
                'd': [0, 1, 2, 0, 1, 2, 3]})
df


Out[453]:
a b c d
0 0 7 one 0
1 1 6 one 1
2 2 5 one 2
3 3 4 two 0
4 4 3 two 1
5 5 2 two 2
6 6 1 two 3

In [454]:
# set_index() 會將其一個或多個columns轉換為 row索引,並創建一個 DataFrame
df2 = df.set_index(['c', 'd'])
df2


Out[454]:
a b
c d
one 0 0 7
1 1 6
2 2 5
two 0 3 4
1 4 3
2 5 2
3 6 1

In [455]:
# 預設情況下,這些columns會被移除,但也可以設定 drop參數將之保留下來
df2 = df.set_index(['c', 'd'], drop = False)
df2


Out[455]:
a b c d
c d
one 0 0 7 one 0
1 1 6 one 1
2 2 5 one 2
two 0 3 4 two 0
1 4 3 two 1
2 5 2 two 2
3 6 1 two 3

In [456]:
# reset_index() 會將 row方向上的多層次索引 移動到 column上
df2 = df.set_index(['c', 'd'])
df2


Out[456]:
a b
c d
one 0 0 7
1 1 6
2 2 5
two 0 3 4
1 4 3
2 5 2
3 6 1

In [457]:
# reset_index() 會將 row方向上的多層次索引 移動到 column上
df2.reset_index()


Out[457]:
c d a b
0 one 0 0 7
1 one 1 1 6
2 one 2 2 5
3 two 0 3 4
4 two 1 4 3
5 two 2 5 2
6 two 3 6 1